from rest_framework import serializers
from .models import User, AddressInfo
import re
from django_redis import get_redis_connection
from celery_tasks.mail.tasks import meiduo_send_active_mail
from meiduo_mall.utils import dict_serializer
from . import constants


class UserRegisterSerializer(serializers.Serializer):
    # 操作的模型类是User
    # 定义字段，指定接收、响应的数据
    id = serializers.IntegerField(read_only=True)
    token = serializers.CharField(read_only=True)
    username = serializers.CharField(
        min_length=5,
        max_length=20,
        error_messages={
            'min_length': '用户名必须为5-20个字符',
            'max_length': '用户名必须为5-20个字符'
        }
    )
    password = serializers.CharField(
        min_length=8,
        max_length=20,
        error_messages={
            'min_length': '密码必须为8-20个字符',
            'max_length': '密码必须为8-20个字符'
        },
        write_only=True
    )
    password2 = serializers.CharField(write_only=True)
    mobile = serializers.CharField(max_length=11)
    sms_code = serializers.IntegerField(write_only=True)
    allow = serializers.BooleanField(write_only=True)

    # class Meta:
    #     model = User
    #     fields = ['username', 'password', 'password2', 'mobile', 'sms_code', 'allow']
    #     extra_kwargs = {
    #         'username': {
    #             'min_length': 5,
    #             'max_length': 20
    #         }
    #     }

    # 定义验证方法
    def validate_username(self, value):
        # 判断用户名是否存在
        if User.objects.filter(username=value).count() > 0:
            raise serializers.ValidationError('用户名已经存在')
        return value

    def validate_mobile(self, value):
        if not re.match(r'^1[3-9]\d{9}$', value):
            raise serializers.ValidationError('手机号格式错误')
        if User.objects.filter(mobile=value).count() > 0:
            raise serializers.ValidationError('手机号已经存在')
        return value

    # def validate_sms_code(self,value):
    #     #从redis中读取验证码，与客户端请求的验证码，对比
    #     redis_cli=get_redis_connection('smscode')
    #     smscode_redis=redis_cli.get('sms_'+)问题：需要读取手机号，转到validate()方法中
    #     return value

    def validate_allow(self, value):
        if value == False:
            raise serializers.ValidationError('请同意协议，才能注册')
        return value

    def validate(self, attrs):
        # 判断两个密码是否一致
        pwd1 = attrs.get('password')
        pwd2 = attrs.get('password2')
        if pwd1 != pwd2:
            raise serializers.ValidationError('两次密码不一致')

        # 判断短信验证码
        # 1.获取请求报文中的验证码
        smscode_request = attrs.get('sms_code')
        # 2.读取redis中的验证码,先获取手机号
        mobile = attrs.get('mobile')
        redis_cli = get_redis_connection('smscode')
        smscode_redis = redis_cli.get('sms_' + mobile)  # bytes
        # 验证码的有效时间为300秒，可能超时
        if smscode_redis is None:
            raise serializers.ValidationError('验证码过期，请重新获取')
        if smscode_request != int(smscode_redis):
            raise serializers.ValidationError('短信验证码错误')

        return attrs

    # 定义create()方法：User.objects.create(username=username,password2=password2)
    def create(self, validated_data):
        # 获取需要的数据
        username = validated_data.get('username')
        password = validated_data.get('password')
        mobile = validated_data.get('mobile')
        # 创建用户对象
        # User.objects.create(username=username,password=password)
        user = User.objects.create_user(username, password=password, mobile=mobile)

        # 状态保持
        from rest_framework_jwt.settings import api_settings
        # 获取载荷方法
        jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
        # 获取签名方法
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
        # 计算载荷
        payload = jwt_payload_handler(user)
        # 计算签名，生成jwt字符串
        token = jwt_encode_handler(payload)
        # 为对象添加属性，用于序列化输出
        user.token = token

        return user


class UserInfoSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ['id', 'username', 'mobile', 'email', 'email_active']


class UserEmailSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ['id', 'email']

    def update(self, instance, validated_data):
        # 修改
        to_email = validated_data.get('email')
        instance.email = to_email
        instance.save()

        # 将链接参数加密
        dict1 = {
            'user_id': instance.id
        }
        str1 = dict_serializer.dumps(dict1, constants.EMAIL_ACTIVE_EXPIRES)

        # 发邮件
        verify_url = 'http://www.meiduo.site:8080/success_verify_email.html?token=' + str1
        meiduo_send_active_mail.delay(to_email, verify_url)

        return instance


class AddressCreateSerializer(serializers.ModelSerializer):
    # 定义关系字段
    province_id = serializers.IntegerField()
    city_id = serializers.IntegerField()
    district_id = serializers.IntegerField()
    # 定义关系属性，不需要接收，但是需要响应
    province = serializers.StringRelatedField(read_only=True)
    city = serializers.StringRelatedField(read_only=True)
    district = serializers.StringRelatedField(read_only=True)

    class Meta:
        model = AddressInfo
        # fields=[]
        # 排序不需要的属性
        exclude = ['create_time', 'update_time', 'user']
        extra_kwargs = {
            'email': {
                'allow_blank': True
            },
            'tel': {
                'allow_blank': True
            }
        }

    def create(self, validated_data):
        user = self.context['request'].user
        # 判断收货地址是否达到上限
        if user.addresses.count() >= constants.USER_ADDRESS_COUNTS_LIMIT:
            raise serializers.ValidationError('已经达到添加上限，不允许继续添加')

        # 在validated_data字典中指定user属性
        validated_data['user'] = user

        address = super().create(validated_data)

        return address
